# class Singleton(object):
#     _instance = None
#     def __new__(cls, *args, **kwargs):
#         if not cls._instance:
#             return super(Singleton, cls).__new__(cls, *args, **kwargs)
#         return cls._instance

# class MySingleton(Singleton):
#     pass

# a = MySingleton()
# b = MySingleton()
# assert a is b


# class g(float):
#     def __new__(cls, kg):
#         return float.__new__(cls, kg * 2)

# a = g(50)


class Field(object):
    
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type

    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)

class StringField(Field):

    def __init__(self, name, *args, **kwargs):
        super(StringField, self).__init__(name, 'varchar(100)')
    
class IntegerField(Field):

    def __init__(self, name, *args, **kwargs):
        super(IntegerField, self).__init__(name, 'bigint')

class ModelMetaclass(type):
    
    def __new__(cls, name, bases, attrs):
        if name == 'Model':
            return type.__new__(cls, name, bases, attrs)
        print('Found model: %s' % name)
        mappings = dict()
        for k, v in attrs.items():
            if isinstance(v, Field):
                print('Found mapping: %s ==> %s' % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs['__mappings__'] = mappings
        attrs['__table__'] = name
        return type.__new__(cls, name, bases, attrs)
    
class Model(dict, metaclass=ModelMetaclass):

    def __init__(self, *args, **kwargs):
        super(Model, self).__init__(*args, **kwargs)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError('Model object has no attribute %s' % key)
    
    def __setattr__(self, key, value):
        self[key] = value

    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v.name)
            params.append('?')
            args.append(getattr(self, k, None))
        sql = ''

class User(Model):

    id = IntegerField('id')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')

u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()
